/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include <myfreertos.h>
#include <FreeRTOS.h>
#include "task.h"
#include "main.h"
#include "Bsp.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* FreeRTOS Task Handles */
osThreadId MotionTaskHandle;
osThreadId SensorTaskHandle;
osThreadId UartTaskHandle;
osThreadId DisplayTaskHandle;
osThreadId KeyTaskHandle;
osThreadId DefaultTaskHandle;
/* USER CODE END Variables */

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );

/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
  *ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
  *ppxIdleTaskStackBuffer = &xIdleStack[0];
  *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
  /* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

void MX_FREERTOS_Init(void)
{
  /* Create the thread(s) */
  /* definition and creation of MotionTask */
  osThreadDef(MotionTask, StartMotionTask, osPriorityRealtime, 0, 512);
  MotionTaskHandle = osThreadCreate(osThread(MotionTask), NULL);

  /* definition and creation of SensorTask */
  osThreadDef(SensorTask, StartSensorTask, osPriorityHigh, 0, 384);
  SensorTaskHandle = osThreadCreate(osThread(SensorTask), NULL);

  /* definition and creation of UartTask */
  osThreadDef(UartTask, StartUartTask, osPriorityAboveNormal, 0, 384);
  UartTaskHandle = osThreadCreate(osThread(UartTask), NULL);

  /* definition and creation of DisplayTask */
  osThreadDef(DisplayTask, StartDisplayTask, osPriorityNormal, 0, 256);
  DisplayTaskHandle = osThreadCreate(osThread(DisplayTask), NULL);

  osThreadDef(KeyTask, StartKeyTask, osPriorityBelowNormal, 0, 128);
  KeyTaskHandle = osThreadCreate(osThread(KeyTask), NULL);

  /* definition and creation of DefaultTask */
  osThreadDef(DefaultTask, StartDefaultTask, osPriorityIdle, 0, 128);
  DefaultTaskHandle = osThreadCreate(osThread(DefaultTask), NULL);
}


/* Task functions */
//用于小车控制
void StartMotionTask(void const * argument)
{
	/* USER CODE BEGIN 5 */
	  /* Infinite loop */
	  for(;;)
	  {
		    Motion_Handle();  // 每10ms执行一次运动控制
        osDelay(10);      // 10ms延时
	  }
	  /* USER CODE END 5 */
}

//串口数据发送
void StartSensorTask(void const * argument)
{
	/* USER CODE BEGIN StartSensorTask */
	  /* Infinite loop */
	  for(;;)
	{
		// IMU数据采集发送(100HZ)
		MPU9250_Read_Data_Handle();
		// 发送速度数据（50Hz）
		uint8_t speed_count = 0;
		if(++speed_count >= 2) {
		 	send_speed_data(car_data.Vx, car_data.Vy, car_data.Vz);
		 	speed_count = 0;
		}
		osDelay(10);  // 100Hz采样率
	}
	  /* USER CODE END StartSensorTask */
}

//串口数据接收处理
void StartUartTask(void const * argument)
{
	/* USER CODE BEGIN StartUartTask */
	  /* Infinite loop */
	  for(;;)
	  {
		uint8_t count = 0;
		if(++count >= 2){
			Process_UART_Data();  // 处理串口数据(50HZ)
			count = 0;
		}
		osDelay(10);	// 100Hz发送频率
	  }
	  /* USER CODE END StartUartTask */
}

//显示相关处理
void StartDisplayTask(void const * argument)
{
	/* USER CODE BEGIN StartDisplayTask */
	uint32_t last_oled_update = 0;
	uint32_t oled_update_interval = 50;  // 50ms更新一次OLED（20Hz刷新率）

	/* Infinite loop */
	for(;;)
	{
	uint32_t now = osKernelSysTick();

	    // 处理LED状态显示
        Bsp_Led_Show_State_Handle();

        // 处理蜂鸣器
        Beep_Timeout_Close_Handle();

		// 3. 更新OLED显示（20Hz刷新率）
        if (now - last_oled_update >= oled_update_interval)
        {
            // 示例：显示速度数据（假设 car_data 是全局变量）
            OLED_ShowNum(1, 4, car_data.Vx, 4);  // 第一行显示 Vx
            OLED_ShowNum(2, 4, car_data.Vy, 4);  // 第二行显示 Vy
            OLED_ShowNum(3, 4, car_data.Vz, 4);  // 第三行显示 Vz

            last_oled_update = now;
        }

        osDelay(10);  // 10ms任务周期（100Hz运行）
	}
	  /* USER CODE END StartDisplayTask */
}


void StartKeyTask(void const * argument)
{
    /* USER CODE BEGIN StartKeyTask */
	uint8_t state = 0;
    for(;;) {
        if(Key1_Mode_Set(Key_One_Press)) {
            Beep_On_Time(50);
            if (state == 0) {
                Motion_Ctrl(350, 0, 0);
                state = 1;
            } else {
                Motion_Stop(STOP_BRAKE);
                state = 0;
            }
        }
        osDelay(50);  // 20Hz按键检测频率
    }
    /* USER CODE END StartKeyTask */
}


void StartDefaultTask(void const * argument)
{
	/* USER CODE BEGIN StartDefaultTask */
	  /* Infinite loop */
	  for(;;)
	  {
	    osDelay(1);
	  }
	  /* USER CODE END StartDefaultTask */
}
/* USER CODE END Application */

